package bard.partnermatchingsystem.service.impl;


import bard.partnermatchingsystem.Common.ErrorCode;
import bard.partnermatchingsystem.domain.Enums.TeamStatusEnum;
import bard.partnermatchingsystem.domain.dto.TeamAddDTO;
import bard.partnermatchingsystem.domain.dto.TeamJoinDTO;
import bard.partnermatchingsystem.domain.dto.TeamQuitDTO;
import bard.partnermatchingsystem.domain.dto.TeamUpdateamDTO;
import bard.partnermatchingsystem.domain.po.Team;
import bard.partnermatchingsystem.domain.po.User;
import bard.partnermatchingsystem.domain.po.UserTeam;
import bard.partnermatchingsystem.domain.vo.UserTeamVO;
import bard.partnermatchingsystem.domain.vo.UserVO;
import bard.partnermatchingsystem.exception.CommonException;
import bard.partnermatchingsystem.mapper.TeamMapper;
import bard.partnermatchingsystem.service.TeamService;
import bard.partnermatchingsystem.service.UserService;
import bard.partnermatchingsystem.service.UserTeamService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.logging.Log;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* @author bard
* @description 针对表【team(队伍)】的数据库操作Service实现
* @createDate 2024-08-04 17:03:41
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements TeamService {
    private final UserTeamService userTeamService;

    private final UserService userService;

    private final TeamMapper teamMapper;

    private final RedissonClient redissonClient;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addTeam(TeamAddDTO teamAddDTO, User loginUser) {
        //判断用户是否登录
        if (loginUser == null){
            throw new CommonException(ErrorCode.NOT_LOGIN);
        }
        //请求信息校验,判断队伍人数是否在1-20人
        int maxNum = Optional.ofNullable(teamAddDTO.getMaxNum()).orElse(0);
        if(maxNum<1||maxNum>20){
            throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍人数超出范围");
        }
        //判断队伍名称是否在1-20个字符
        String teamName= teamAddDTO.getName();
        if(teamName.length()>20|| teamName.isEmpty()){
            throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍名称超出范围");
        }
        //判断队伍描述是否在1-512个字符
        if (teamAddDTO.getDescription().length()>512){
            throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍描述超出范围");
        }
        //判断队伍状态是否公开如果加密必须设置密码且密码在6-32个字符
        if (teamAddDTO.getStatus()==1){
            if (teamAddDTO.getPassword().length()<6||teamAddDTO.getPassword().length()>32){
                throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍密码超出范围");
            }
        }
        //判断超时时间大于当前时间
        if (teamAddDTO.getExpireTime().before(new java.util.Date())){
            throw new CommonException(ErrorCode.PARAMS_ERROR,"超时时间小于当前时间");
        }
        // 判断用户最多创建五个队伍
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", loginUser.getId());
        long count = this.count(queryWrapper);
        int maxTeamsAllowed = 5;
        if (count > maxTeamsAllowed) {
            throw new CommonException(ErrorCode.PARAMS_ERROR, "最多创建" + maxTeamsAllowed + "个队伍");
        }
        Team team = new Team();
        team.setUserId(loginUser.getId());
        BeanUtils.copyProperties(teamAddDTO,team);
        boolean save = this.save(team);
        if (!save){
            throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍创建失败");
        }
        //保存队伍信息到队伍信息表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(team.getUserId());
        userTeam.setTeamId(team.getId());
        userTeam.setJoinTime(new Date());
        save = userTeamService.save(userTeam);
        if (!save){
            throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍创建失败");
        }
        return team.getId();
    }

    @Override
    public List<UserTeamVO> listTeams(String searchText, int status, Boolean isAdmin, User loginUser) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        //判断查询队伍状态，只有管理员可以查询私有队伍
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
        if (teamStatusEnum==null){
            teamStatusEnum=TeamStatusEnum.PUBLIC;
        }
        if (isAdmin && !teamStatusEnum.equals(TeamStatusEnum.PUBLIC)) {
            queryWrapper
                    .ne("status", 0)
                    .and(qw -> qw.like("name", searchText).or().like("description", searchText));
        }
        else {
            queryWrapper
                    .eq("status", 0)
                    .and(qw -> qw.like("name", searchText).or().like("description", searchText));
            }
        queryWrapper.and(i->i.gt("expire_time",new Date()).or().isNull("expire_time"));
        List<Team> Teamlist = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(Teamlist)) {
            return new ArrayList<>();
        }
        List<UserTeamVO> userTeamVOList=new ArrayList<>();
        //关联查询所有队伍的创建人信息
        for (Team team : Teamlist) {
            Long id = team.getId();
            Long createUserId = team.getUserId();
            QueryWrapper<UserTeam> query = new QueryWrapper<>();
            query.eq("team_id",id);
            if(createUserId==null){
                continue;
            }
            UserTeamVO userTeamVO=new UserTeamVO();
            BeanUtils.copyProperties(team, userTeamVO);
            userTeamVO.setTeamId(team.getId());
            User user = userService.getById(createUserId);
            if (user!=null){
                UserVO userVO=new UserVO();
                BeanUtils.copyProperties(user,UserVO.class);
                userTeamVO.setCreateUser(userVO);
            }
            long count = userTeamService.count(query);
            userTeamVO.setHasJoinNum(Math.toIntExact(count));
            userTeamVOList.add(userTeamVO);
        }
        List<Long>TeamIdList=userTeamVOList.stream().map(UserTeamVO::getTeamId).toList();
        //查询出当前登录用户加入的队伍
        QueryWrapper<UserTeam> UserTeamQueryWrapper = new QueryWrapper<>();
        UserTeamQueryWrapper.eq("user_id",loginUser.getId());
        UserTeamQueryWrapper.in("team_id",TeamIdList);
        List<UserTeam> userTeamList = userTeamService.list(UserTeamQueryWrapper);
        //如果查询出的队伍有和用户队伍相同的队伍则设置hasJoin为true
        Set<Long> hasJoinTeamIdSet = userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
        userTeamVOList.forEach(userTeamVO -> {
            boolean hasJoin = hasJoinTeamIdSet.contains(userTeamVO.getTeamId());
            userTeamVO.setHasJoin(hasJoin);
        });
        return userTeamVOList;
    }

    @Override
    public boolean updateTeam(TeamUpdateamDTO teamUpdateamDTO, User loginUser) {
        //判断传入参数是否为空
        if (teamUpdateamDTO == null) {
            throw new CommonException(ErrorCode.PARAMS_ERROR);
        }
        //判断队伍是否存在
        Team oldTeam = getTeam(teamUpdateamDTO.getId());
        //判断用户是否为队长或者是管理员 判断是否为队长必须在前面
        if (!oldTeam.getUserId().equals(loginUser.getId())&&!userService.isAdmin(loginUser)){
            throw new CommonException(ErrorCode.NO_AUTH);
        }
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(teamUpdateamDTO.getStatus());
        if (teamStatusEnum==TeamStatusEnum.SECRET){
            if(StringUtils.isBlank(oldTeam.getPassword())&& StringUtils.isBlank(teamUpdateamDTO.getPassword())){
                throw new CommonException(ErrorCode.PARAMS_ERROR,"加密队伍必须设置密码");
            }
        }
        Team team=new Team();
        BeanUtils.copyProperties(teamUpdateamDTO,team);
        return this.updateById(team);
    }

    @Override
    public Boolean joinTeam(TeamJoinDTO teamJoinDTO, User loginUser) {
        if (teamJoinDTO==null){
            throw new CommonException(ErrorCode.PARAMS_ERROR);
        }
        RLock lock = redissonClient.getLock("bard:team:join_team");
        try {
            while (true){
                if(lock.tryLock(0,-1, TimeUnit.MILLISECONDS)){
                    Long id = loginUser.getId();
                    Long teamId = teamJoinDTO.getTeamId();
                    //判断队伍id是否为空
                    Team team = getTeam(teamId);
                    //判断是否为私有队伍
                    if (team.getStatus()==1){
                        throw new CommonException(ErrorCode.NO_AUTH,"无法加入私有队伍");
                    }
                    //判断队伍是否过期
                    if (team.getExpireTime().before(new Date())){
                        throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍已过期");
                    }
                    //判断队伍人数是否已满
                    Integer maxNum = team.getMaxNum();
                    if (maxNum<=userTeamService.count(new QueryWrapper<UserTeam>().eq("team_id",teamId))){
                        throw new CommonException(ErrorCode.PARAMS_ERROR,"队伍已满");
                    }
                    //一个用户最多加入五个队伍
                    if (userTeamService.count(new QueryWrapper<UserTeam>().eq("user_id",id))>5){
                        throw new CommonException(ErrorCode.PARAMS_ERROR,"用户最多加入五个队伍");
                    }
                    //判断登录用户是否已经加入了该队伍
                    UserTeam userTeam = userTeamService.getOne(new QueryWrapper<UserTeam>().
                            eq("user_id", id).
                            eq("team_id", teamId));
                    if (userTeam!=null){
                        throw new CommonException(ErrorCode.PARAMS_ERROR,"已经加入过该队伍");
                    }
                    if (StringUtils.isNotBlank(team.getPassword())&&!team.getPassword().equals(teamJoinDTO.getPassword())){
                        throw new CommonException(ErrorCode.PARAMS_ERROR,"密码错误");
                    }
                    userTeam=new UserTeam();
                    userTeam.setUserId(id);
                    userTeam.setTeamId(teamId);
                    userTeam.setJoinTime(new Date());
                    return userTeamService.save(userTeam);
                }
            }
        } catch (InterruptedException e) {
            log.error("doCacheRecommendUser error", e);
            return false;
        } finally {
            // 只能释放自己的锁
            if (lock.isHeldByCurrentThread()) {
                System.out.println("unLock: " + Thread.currentThread().getId());
                lock.unlock();
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean quitTeam(TeamQuitDTO teamquitDTO, User loginUser) {
        Long teamId = teamquitDTO.getTeamId();
        Team team = getTeam(teamId);
        //校验是否已经加入队伍
        UserTeam userTeam = userTeamService.getOne(new QueryWrapper<UserTeam>().
                eq("user_id", loginUser.getId()).
                eq("team_id", teamId));
        if (userTeam==null){
            throw new CommonException(ErrorCode.NULL_ERROR,"未加入队伍");
        }
        if (team.getUserId().equals(loginUser.getId())){
            //队伍队长退出队伍
            if (userTeamService.count(new QueryWrapper<UserTeam>().eq("team_id", teamId))==1){
                //队伍只有一个人，直接解散
                this.removeById(teamId);
            }else {
                //队伍还有其他人，将队长设置为其他人
                List<UserTeam> userTeamList = userTeamService.list(new QueryWrapper<UserTeam>()
                        .eq("team_id", teamId)
                        .ne("user_id", loginUser.getId())
                        .orderByAsc("create_time"));
                //查找除了队长以外离队伍创建时间最近的队员
                if (CollectionUtils.isNotEmpty(userTeamList)) {
                    UserTeam earliestUser = userTeamList.get(0);
                    team.setUserId(earliestUser.getUserId());
                    teamMapper.updateById(team);
                }
            }
            //删除队伍关系表记录
            userTeamService.remove(new QueryWrapper<UserTeam>().eq("user_id", loginUser.getId()).eq("team_id", teamId));
        }else {
            //队伍成员退出队伍
            userTeamService.remove(new QueryWrapper<UserTeam>().eq("user_id", loginUser.getId()).eq("team_id", teamId));
        }
        return true;
    }

    @Override
    public boolean removeTeam(Long teamId, User loginUser) {
        //判断队伍是否存在
        Team team = getTeam(teamId);
        //校验是不是队长
        if (!team.getUserId().equals(loginUser.getId())){
            throw new CommonException(ErrorCode.NO_AUTH,"没有权限");
        }
        //删除队伍关系和队伍
        boolean result = userTeamService.remove(new QueryWrapper<UserTeam>().
                eq("team_id", teamId));
        if (!result){
            throw new CommonException(ErrorCode.SYSTEM_ERROR,"删除队伍关系失败");
        }
        return this.remove(new QueryWrapper<Team>().eq("id", teamId));
    }

    @Override
    public List<UserTeamVO> getMycreateTeams(String searchText, User loginUser) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        Long loginUserId = loginUser.getId();
        queryWrapper.eq("user_id", loginUserId);
        List<Team> Teamlist = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(Teamlist)) {
            return new ArrayList<>();
        }
        List<UserTeamVO> userTeamVOList=new ArrayList<>();
        //关联查询所有队伍的创建人信息
        for (Team team : Teamlist) {
            Long id = team.getId();
            Long createUserId = team.getUserId();
            QueryWrapper<UserTeam> query = new QueryWrapper<>();
            query.eq("team_id",id);
            if(createUserId==null){
                continue;
            }
            UserTeamVO userTeamVO=new UserTeamVO();
            BeanUtils.copyProperties(team, userTeamVO);
            userTeamVO.setTeamId(team.getId());
            User user = userService.getById(createUserId);
            if (user!=null){
                UserVO userVO=new UserVO();
                BeanUtils.copyProperties(user,UserVO.class);
                userTeamVO.setCreateUser(userVO);
            }
            long count = userTeamService.count(query);
            userTeamVO.setHasJoinNum(Math.toIntExact(count));
            userTeamVOList.add(userTeamVO);
        }
        List<Long>TeamIdList=userTeamVOList.stream().map(UserTeamVO::getTeamId).toList();
        //查询出当前登录用户加入的队伍
        QueryWrapper<UserTeam> UserTeamQueryWrapper = new QueryWrapper<>();
        UserTeamQueryWrapper.eq("user_id",loginUser.getId());
        UserTeamQueryWrapper.in("team_id",TeamIdList);
        List<UserTeam> userTeamList = userTeamService.list(UserTeamQueryWrapper);
        //如果查询出的队伍有和用户队伍相同的队伍则设置hasJoin为true
        Set<Long> hasJoinTeamIdSet = userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
        userTeamVOList.forEach(userTeamVO -> {
            boolean hasJoin = hasJoinTeamIdSet.contains(userTeamVO.getTeamId());
            userTeamVO.setHasJoin(hasJoin);
        });
        return userTeamVOList;
    }

    @Override
    public List<UserTeamVO> getMyjoinTeams(String searchText, User loginUser) {
        //查询当前用户的关系表获取加入了那些队伍的id
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        Long loginUserId = loginUser.getId();
        queryWrapper.eq("user_id", loginUserId);
        List<UserTeam> UserTeamlist = userTeamService.list(queryWrapper);
        Set<Long>teamIdSet=UserTeamlist.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
        List<Team> Teamlist = this.listByIds(teamIdSet);

        if (CollectionUtils.isEmpty(Teamlist)) {
            return new ArrayList<>();
        }
        List<UserTeamVO> userTeamVOList=new ArrayList<>();
        //关联查询所有队伍的创建人信息
        for (Team team : Teamlist) {
            Long id = team.getId();
            Long createUserId = team.getUserId();
            QueryWrapper<UserTeam> query = new QueryWrapper<>();
            query.eq("team_id",id);
            if(createUserId==null){
                continue;
            }
            UserTeamVO userTeamVO=new UserTeamVO();
            BeanUtils.copyProperties(team, userTeamVO);
            userTeamVO.setTeamId(team.getId());
            User user = userService.getById(createUserId);
            if (user!=null){
                UserVO userVO=new UserVO();
                BeanUtils.copyProperties(user,UserVO.class);
                userTeamVO.setCreateUser(userVO);
            }
            long count = userTeamService.count(query);
            userTeamVO.setHasJoinNum(Math.toIntExact(count));
            userTeamVOList.add(userTeamVO);
        }
        List<Long>TeamIdList=userTeamVOList.stream().map(UserTeamVO::getTeamId).toList();
        //查询出当前登录用户加入的队伍
        QueryWrapper<UserTeam> UserTeamQueryWrapper = new QueryWrapper<>();
        UserTeamQueryWrapper.eq("user_id",loginUser.getId());
        UserTeamQueryWrapper.in("team_id",TeamIdList);
        List<UserTeam> userTeamList = userTeamService.list(UserTeamQueryWrapper);
        //如果查询出的队伍有和用户队伍相同的队伍则设置hasJoin为true
        Set<Long> hasJoinTeamIdSet = userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
        userTeamVOList.forEach(userTeamVO -> {
            boolean hasJoin = hasJoinTeamIdSet.contains(userTeamVO.getTeamId());
            userTeamVO.setHasJoin(hasJoin);
        });
        return userTeamVOList;
    }

    public Team getTeam(Long teamId) {
        if (teamId==null||teamId<0){
            throw new CommonException(ErrorCode.PARAMS_ERROR);
        }
        //校验队伍是否存在
        Team team = teamMapper.selectById(teamId);
        if (team==null){
            throw new CommonException(ErrorCode.NULL_ERROR,"队伍不存在");
        }
        return team;
    }

//    @Override
//    public List<UserTeamVO> listTeams(TeamQuery teamQuery, Boolean isAdmin) {
//        QueryWrapper<Team> queryWrapper=new QueryWrapper<>();
//        //队伍id
//        Long id = teamQuery.getId();
//        if(id!=null&&id>=0){
//            queryWrapper.eq("id",teamQuery.getId());
//        }
//        //队伍名称
//        if(StringUtils.isNotBlank(teamQuery.getName())){
//            queryWrapper.like("name",teamQuery.getName());
//        }
//        //队伍描述
//        if(StringUtils.isNotBlank(teamQuery.getDescription())){
//            queryWrapper.like("description",teamQuery.getDescription());
//        }
//        //最大人数
//        Integer maxNum = teamQuery.getMaxNum();
//        if(maxNum!=null&&maxNum>=0){
//            queryWrapper.eq("max_num",teamQuery.getMaxNum());
//        }
//        //队长id
//        Long userId = teamQuery.getUserId();
//        if(userId!=null&&userId>=0){
//            queryWrapper.eq("user_id",teamQuery.getUserId());
//        }
//        //队伍状态
//        Integer status = teamQuery.getStatus();
//        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
//        if (teamStatusEnum==null){
//            teamStatusEnum=TeamStatusEnum.PUBLIC;
//        }
//        if (!isAdmin && teamStatusEnum.equals(TeamStatusEnum.PRIVATE)) {
//            throw new CommonException(ErrorCode.NO_AUTH);
//        }
//        queryWrapper.eq("status",teamStatusEnum.getValue());
//
//        if(teamQuery.getStatus()>=0){
//            queryWrapper.eq("status",teamQuery.getStatus());
//        }
//
//        //不展示已经过期的队伍 expire_time<=new Date()或者expire_time为空
//        queryWrapper.and(i->i.gt("expire_time",new Date()).or().isNull("expire_time"));
//        List<Team> Teamlist = this.list(queryWrapper);
//        if (CollectionUtils.isEmpty(Teamlist)) {
//            return new ArrayList<>();
//        }
//        List<UserTeamVO> userTeamVOList=new ArrayList<>();
//        //关联查询所有队伍的创建人信息
//        for (Team team : Teamlist) {
//            Long createUserId = team.getUserId();
//            if(createUserId==null){
//                continue;
//            }
//            UserTeamVO userTeamVO=new UserTeamVO();
//            BeanUtils.copyProperties(team, userTeamVO);
//            User user = userService.getById(createUserId);
//            if (user!=null){
//                UserVO userVO=new UserVO();
//                BeanUtils.copyProperties(user,UserVO.class);
//                userTeamVO.setCreateUser(userVO);
//            }
//            userTeamVOList.add(userTeamVO);
//        }
//        return userTeamVOList;
//    }
}




